package oboe.controllers.soundController;

import flash.events.Event;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.utils.Dictionary;
import flash.utils.getTimer;

import oboe.core.Oboe;
import oboe.core.SigSlot;
import oboe.resources.Files;

class SoundController extends SigSlot
{
public static inline var instance:SigSlot = new SoundController();

private var music:ManagedSound;
private var sounds:Dictionary;
private var soundClasses:Dictionary;

private var muteTime:Float = 0;
private var isMuted:Bool;

public function new()
{
	super( );
	sounds = new Dictionary();
	soundClasses = new Dictionary();
	if( Oboe.flags["NO_SOUND"] )
	{
	Oboe.flags["SOUNDMUTED"] = true;
	isMuted = true;
	}
	else
	{
	Oboe.flags["SOUNDMUTED"] = false;
	isMuted = false;
	}
}

public function slot_playMusic( name:String ):Void
{
	if( music ) music.stop();
	if( name != null )
	{
	music = new ManagedSound( Sound(Files.getFile( name )), onSoundEnd, name, "" );
	}
	music.play( 0, -1 );
	if( isMuted )
	{
	music.pause();
	}
}

public function slot_stopMusic():Void
{
	music.stop();
}

public function slot_stopSoundClass( soundClass:String ):Void
{
	if( !(soundClass in this.soundClasses) ) return;
	var scd:Dictionary = this.soundClasses[ soundClass ];
	for each( var s:ManagedSound in scd )
	{
	s.stopAll();
	}
}

public function slot_playSound( name:String, loops:Int=1, soundClass:String="" ):Void
{
	if(isMuted) return;
	var snd:ManagedSound;

	if( Oboe.flags["SOUND_OVERLAP"] === false )
	{
	this.slot_stopSoundClass( soundClass );
	}
	
	if( !(name in sounds) )
	{
	sounds[ name ] = new ManagedSound( Files.getFile(name) as Sound, onSoundEnd, name, soundClass );
	}
	
	snd = sounds[ name ];
	
	if( soundClass == "" ) soundClass = name;
	if( !(soundClass in this.soundClasses) )
	{
	this.soundClasses[ soundClass ] = new Dictionary( true );
	}
	this.soundClasses[ soundClass ][ snd ] = snd;
	
	
	
	snd.play( 0, loops);
}

private function onSoundEnd( sound:ManagedSound, channel:ManagedChannel ):Void
{
	if( sound.getChannelCount() == 1 )
	{
	delete sounds[ sound.getName() ];
	delete soundClasses[ sound.getSoundClass() ][ sound ];
	}
	else
	{
	sound.removeChannel( channel );
	}
}

public function slot_pauseSounds():Void
{
	if( this.music ) music.pause();
	for each( var snd:ManagedSound in this.sounds )
	{
	snd.pause();
	}
	Oboe.flags["SOUNDMUTED"] = true;
}

public function slot_continueSounds():Void
{
	if( isMuted ) return;
	
	if( this.music ) music.resumeAfter( 0 );
	for each( var snd:ManagedSound in this.sounds )
	{
	snd.resumeAfter( 0 );
	}
	Oboe.flags["SOUNDMUTED"] = false;
}

public function slot_onToggleMute():Void
{
	if( this.isMuted )
	{
	slot_unmute();
	}
	else
	{
	slot_mute();
	}	
}

public function slot_mute():Void
{
	this.muteTime = getTimer();
	this.isMuted = true;
	this.slot_pauseSounds();
}

public function slot_unmute():Void
{
	if( !this.isMuted ) return;
	var delta:Float = getTimer() - this.muteTime;
	if( this.music ) this.music.resumeAfter( delta );
	for each( var snd:ManagedSound in this.sounds )
	{
	snd.resumeAfter( delta );
	}
	this.isMuted = false;
	Oboe.flags["SOUNDMUTED"] = false;
}
}